package gis

import (
	"dgo/goutils/utils"
)

/*
*
@GELOC,Time,Lat,Lon,Alt,North,East,Height,SatNum,PosStat,PDOP,HRMS,VRMS,age,Speed,Dir,设备SN,,,*校验
@GELOC,2023-01-11T16:40:24,23.1665838550,113.4301137800,57.8320,0.0000,0.0000,0.0000,52,1,0.723,0.758,1.231,0,0.0190,289.5570,NET1P3A2200011,,,*BB<CR><LF>
*/
type GeoDecoder struct {
	decodeState int
	starIdx     int // *的索引
	cache       utils.BytesBuilder
	LastData    string
	OnDataFunc  func(sender *GeoDecoder, data string)
}

func NewGeoDecoder() *GeoDecoder {
	rval := &GeoDecoder{}
	return rval
}

func (this *GeoDecoder) Reset() {
	this.cache.Reset()
	this.decodeState = 1
	this.starIdx = 0
}

func (this *GeoDecoder) InputText(txt string) {
	this.InputBuf([]byte(txt))
}

func (this *GeoDecoder) InputBuf(buf []byte) int {
	rval := 0
	for i := 0; i < len(buf); i++ {
		if this.InputByte(buf[i]) == 1 {
			rval++
		}
	}
	return rval
}

func (this *GeoDecoder) GetDataText() string {
	return this.cache.String()
}

func (this *GeoDecoder) CheckValid() bool {
	str := this.cache.String()
	if str[0] != '@' {
		return false
	}
	if len(str) < 4 {
		return false
	}
	crc0 := str[len(str)-2:]
	str = str[1 : len(str)-3]
	crc := CRC([]byte(str))
	v := utils.HexToInt(crc0)
	r := crc == byte(v)
	return r
}

func (this *GeoDecoder) CacheBuf() []byte {
	return this.cache.Bytes()
}

func (this *GeoDecoder) InputByte(v byte) int {
	if this.decodeState <= 0 {
		this.Reset()
	}

	this.cache.WriteByte(v)
	l := this.cache.Len()
	if l == 1 {
		if v != '@' {
			this.decodeState = -1
			return 0
		}
	} else if l <= 8 {
		if v == '@' && l > 1 { // @@GELOC, @PXXXX@GELOC
			this.cache.Delete(0, l-1)
			return 0
		}
		if IsNmeaChr(v) {
			return 0
		}
		this.decodeState = -1
		return 0
	} else {
		if !IsNmeaChr(v) {
			this.decodeState = -1
			return 0
		}
		if this.starIdx > 0 {
			if this.starIdx+3 == this.cache.Len() { // 校验码
				this.decodeState = 0
				str := this.cache.String()
				this.LastData = str
				if this.OnDataFunc != nil {
					this.OnDataFunc(this, str)
				}
				return 1
			}
		} else {
			if this.cache.Len() > 512 { // 超过512 还没有结束
				this.decodeState = -1
				return -1
			}
			if v == '*' {
				this.starIdx = this.cache.Len() - 1 // 星号的位置
			}
		}
	}
	return 0

}
